/**
 * Project Name:fire-industry-DM-center
 * File Name:PatentServiceImpl.java
 * Package Name:com.firestone.service.patent.impl
 * Date:2018年4月17日上午9:20:43
 *
*/

package com.firestone.service.patent.impl;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Future;

import org.apache.lucene.search.join.ScoreMode;
import org.elasticsearch.index.query.NestedQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.ScrolledPage;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;

import com.firestone.bean.entity.elasticsearch.dm.DmMapPatent;
import com.firestone.bean.entity.elasticsearch.im.DmImPatent;
import com.firestone.bean.entity.elasticsearch.im.DmImProjectStatic;
import com.firestone.core.constants.ConstantDmKey;
import com.firestone.core.constants.ConstantKey;
import com.firestone.core.utils.TransUtil;
import com.firestone.dao.repository.DmImPatentRepository;
import com.firestone.service.elasticsearch.IMyElasticsearchService;
import com.firestone.service.patent.IPatentService;

/**
 * @Description: TODO(专利业务实现类)
 * @author CAIYJ
 * @date 2018年4月17日 上午9:20:43
 */
@Service
public class PatentServiceImpl implements IPatentService {

    @Autowired
    private DmImPatentRepository imPatentRepository;

    @Autowired
    private ElasticsearchOperations elasticsearchOperations;

    @Autowired
    private IMyElasticsearchService myElasticsearchService;

    @Async
    @Override
    public void push(SearchQuery searchQuery, Long... mapIds) throws Exception {
        if (null == searchQuery) {
            return;
        }
        searchQuery
                .setPageable(PageRequest.of(ConstantKey.ES_DEFAULT_SCROLL_PAGE,
                        ConstantKey.ES_DEFAULT_SCROLL_SIZE));
        ScrolledPage<DmMapPatent> scroll = (ScrolledPage<DmMapPatent>) elasticsearchOperations
                .startScroll(ConstantKey.ES_DEFAULT_SCROLL_TIME_IN_MILLIS,
                        searchQuery, DmMapPatent.class);
        Set<String> ids = null;
        while (scroll.hasContent()) {
            ids = new HashSet<>();
            for (DmMapPatent dmMapPatent : scroll.getContent()) {
                ids.add(dmMapPatent.getId());
            }
            Iterable<DmImPatent> iterable = imPatentRepository.findAllById(ids);
            Iterable<DmImPatent> insertPatents = saveAllBuilder(
                    scroll.getContent(), iterable, mapIds);
            imPatentRepository.saveAll(insertPatents);
            scroll = (ScrolledPage<DmMapPatent>) elasticsearchOperations
                    .continueScroll(scroll.getScrollId(),
                            ConstantKey.ES_DEFAULT_SCROLL_TIME_IN_MILLIS,
                            DmMapPatent.class);
        }
    }

    /**
     * @Description: TODO(生成更新/新增专利信息)
     * @param source
     * @param target
     * @param mapIds
     * @return
     * @throws Exception
     * @author CAIYJ
     * @date 2018年4月17日 上午9:54:36
     * @lastModifier CAIYJ
     */
    private Iterable<DmImPatent> saveAllBuilder(Iterable<DmMapPatent> source,
            Iterable<DmImPatent> target, Long... mapIds) throws Exception {
        List<DmImPatent> list = new ArrayList<>();
        if (null != source) {
            DmImPatent patent = null;
            for (DmMapPatent dmMapPatent : source) {
                patent = new DmImPatent();
                BeanUtils.copyProperties(dmMapPatent, patent);
                if (null != target) {
                    for (DmImPatent dmImPatent : target) {
                        if (dmMapPatent.getId().equals(dmImPatent.getId())) {
                            TransUtil.fieldTransExcludeRecord(dmImPatent,
                                    patent, DmImPatent.class);
                            TransUtil.categoryTransUp(dmImPatent, patent,
                                    mapIds);
                            break;
                        }
                    }
                } else {
                    TransUtil.categoryTransUp(null, patent, mapIds);
                }
            }
        }
        return list;
    }

    @Async
    @Override
    public void pull(SearchQuery searchQuery, Long... mapIds) throws Exception {
        if (null == searchQuery) {
            return;
        }
        searchQuery
                .setPageable(PageRequest.of(ConstantKey.ES_DEFAULT_SCROLL_PAGE,
                        ConstantKey.ES_DEFAULT_SCROLL_SIZE));
        ScrolledPage<DmImPatent> scroll = (ScrolledPage<DmImPatent>) elasticsearchOperations
                .startScroll(ConstantKey.ES_DEFAULT_SCROLL_TIME_IN_MILLIS,
                        searchQuery, DmImPatent.class);
        List<DmImPatent> insertProjects = null;
        List<DmImPatent> deleteProjects = null;
        while (scroll.hasContent()) {
            insertProjects = new ArrayList<>();
            deleteProjects = new ArrayList<>();
            for (DmImPatent dmImPatent : scroll.getContent()) {
                TransUtil.categoryTransDown(dmImPatent, mapIds);
                if (dmImPatent.getCategory() != null
                        && dmImPatent.getCategory().size() > 0) {
                    insertProjects.add(dmImPatent);
                } else {// 产业地图DM层企业category为空，则从DM中移除
                    deleteProjects.add(dmImPatent);
                }
            }
        }
    }

    @Async
    @Override
    public Future<Map<String, Long>> projectPatentNum(
            List<DmImProjectStatic> list, Set<String> ids) throws Exception {
        if (null == list || list.size() == 0 || null == ids
                || ids.size() == 0) {
            return new AsyncResult<Map<String, Long>>(null);
        }
        NestedQueryBuilder query = QueryBuilders.nestedQuery(
                ConstantDmKey.org_info,
                QueryBuilders.termsQuery(ConstantDmKey.org_info_org_id, ids),
                ScoreMode.Total);
        Map<String, Long> aggs = myElasticsearchService.nestedAggs(query,
                "info", ConstantDmKey.org_info, "id",
                ConstantDmKey.org_info_org_id, DmImPatent.class);
        return new AsyncResult<Map<String, Long>>(aggs);
    }
}
